package com.lry.jvm;


import com.lry.jvm.instructions.base.BytecodeReader;
import com.lry.jvm.instructions.base.Instruction;
import com.lry.jvm.instructions.base.InstructionFactory;
import com.lry.jvm.rtda.Frame;
import com.lry.jvm.rtda.JThread;
import com.lry.jvm.rtda.heap.JMethod;

public class Interpreter {

    public static void execute(JMethod mainMethod) throws Exception {

        JThread thread = new JThread();
        Frame frame =  thread.newFrame(mainMethod);

        thread.pushFrame(frame);
        loop(thread,true);
    }
    //[-69, 0, 5, 89, -73, 0, 6, 76, -78, 0, 3, 5, -74, 0, 4, -79]
    private static void loop(JThread thread,boolean print) throws Exception {
        BytecodeReader reader = new BytecodeReader();
        byte opcode;
        while(true){
            //一直拿线程的顶部栈帧去执行方法
            Frame frame = thread.peekFrame();
            if(print)
            System.out.println("\n-----------"+frame.getMethod().getJClass().getName()+"----"+frame.getMethod().getName()+"----"+frame.getMethod().getDescriptor()+"---------------------------");

            //获取方法执行的pc计数
            int pc = frame.getNextPc();
            //线程设置pc
            thread.setPc(pc);
            //拿到当前方法的字节码
            byte[] codes = frame.getMethod().getCode();
            reader.reset(codes,pc);

            //指令码
            if(print)
            System.out.println("pc:" + reader.getPc());
            opcode = reader.read8();
            if(print)
            System.out.println("opcode:" + opcode);

            //指令码获取指令
            Instruction instruction = InstructionFactory.getByOpcode(opcode);
            if(print)
            System.out.println("op:" + instruction.getReName());
            if(print)
            System.out.println("localVars:" + frame.getLocalVars());

            instruction.fetchOperands(reader);
            frame.setNextPc(reader.getPc());
            //执行当前帧
            instruction.execute(frame);
            if(print)
            System.out.println("-----------"+frame.getMethod().getJClass().getName()+"----"+frame.getMethod().getName()+"----"+frame.getMethod().getDescriptor()+"---------------------------\n");

            //当线程没有栈帧才算是执行完毕
            if(thread.isStackEmpty()){
                break;
            }
        }

    }


}
